﻿using AutoMapper;
using Lanbt.Core.Entity.Dto;
using Lanbt.Core.Entity.Dto.lanbt_power;
using Lanbt.Core.Entity.Dto.lanbt_role;
using Lanbt.Core.Entity.EntityDB;
using Lanbt.Core.Repository.SqlService.IRepository;
using Lanbt.Core.Service.SqlService.IService;
using Lanbt.Core.Utility.Extent;

namespace Lanbt.Core.Service.SqlService
{
    public class RoleService : IRoleService
    {
        /// <summary>
        /// 角色名称策略
        /// </summary>
        private readonly string[] roleNamePloy = new string[]
        {
            "admin","administrator","admins","超级管理员"
        };

        private readonly IRoleRepository _roleRepository;
        private readonly IUserRepository _userRepository;


        private readonly IPowerService _powerService;

        private readonly IMapper _mapper;

        public RoleService(IRoleRepository roleRepository, IUserRepository userRepository,IMapper mapper,IPowerService powerService)
        {
            _roleRepository = roleRepository;
            _userRepository = userRepository;
            _mapper = mapper;
            _powerService = powerService;
        }

        public async Task<ResultOutput<IList<XM_SelectOutput>>> QueryRolesByUserId(string userId)
        {
            var res = new ResultOutput<IList<XM_SelectOutput>>();

            var user = await _userRepository.GetUserById(userId);
            if (user.IsNull())
            {
                return res.AddError("用户不存在，请刷新重试");
            }

            var roles = await _roleRepository.GetAll();
            var xm_selectList = _mapper.Map<List<XM_SelectOutput>>(roles);

            if (user.RoleIdList.Count > 0)
            {
                foreach (var xm_select in xm_selectList)
                {
                    if (user.RoleIdList.Contains(xm_select.value))
                    {
                        xm_select.selected = true;
                    }
                }
            }

            return res.ResultInput(xm_selectList);
        }

        public async Task<PagesResultOutput<lanbt_role>> QueryPagesRole(QueryPagesRoleInput input)
        {
            var where = Extensions.Load<lanbt_role>();
            if (input.Name.IsNotNull())
            {
                where = where.And(q => q.Name.Contains(input.Name));
            }
            var res = await _roleRepository.QueryToPageListOrderBy(input.PageIndex, input.PageSize, where, q => q.CreateTime);
            return new PagesResultOutput<lanbt_role>(res.Item1, res.Item2);
        }

        public async Task<ResultOutput<IList<TreeData>>> QueryRolePowerTreedata(string id)
        {
            var res = new ResultOutput<IList<TreeData>>();

            var role = await _roleRepository.FirstOrDefault(id);
            if (role.IsNull())
            {
                return res.AddError("角色不存在，请刷新重试");
            }
            var powerIds = role.PowerIds?.Split(',');

            var treeDatas = await _powerService.QueryPowerTreeData();

            if(powerIds.IsNotNull() && powerIds.Length > 0)
            {
                await RecursionForEachTreeData(treeDatas.ToList(), powerIds);
            }

            return res.ResultInput(treeDatas);
        }

        /// <summary>
        /// 递归遍历树形数据
        /// </summary>
        /// <param name="trees"></param>
        /// <param name="powerIds"></param>
        /// <returns></returns>
        private async Task RecursionForEachTreeData(List<TreeData> trees, string[] powerIds)
        {
            foreach (var item in trees)
            {
                if (item.Children.Count == 0 && powerIds.Any(q => q == item.Id))
                {
                    item.Checked = true;
                }
                await RecursionForEachTreeData(item.Children, powerIds);
            }
        }

        public async Task<ResultOutput<string>> Insert(string name)
        {
            var res = new ResultOutput<string>();
            if (roleNamePloy.Contains(name.ToLower()))
            {
                return res.AddError("不能创建系统角色");
            }
            var count = await _roleRepository.Count(q => q.Name == name);
            if (count > 0)
            {
                return res.AddError($"已有角色【{name}】");
            }
            var role = new lanbt_role
            {
                Name = name
            };
            var id = await _roleRepository.InsertOne(role);
            return res.ResultInput(id);
        }

        public async Task<ResultOutput<string>> DeleteById(string id)
        {
            var res = new ResultOutput<string>();
            var count = await _roleRepository.Count(q => q.ID == id);
            if (count == 0)
                return res.AddError("角色不存在");
            await _roleRepository.Delete_false(id);
            return res.ResultInput("删除成功");
        }

        public async Task<ResultOutput<string>> DeleteByIds(List<string> ids)
        {
            var res = new ResultOutput<string>();
            var count = await _roleRepository.Count(q =>ids.Contains(q.ID));
            if (count == 0)
                return res.AddError("角色不存在");
            await _roleRepository.Delete_false(ids);
            return res.ResultInput("删除成功");
        }

        public async Task<ResultOutput<string>> Update(UpdateRoleInput input)
        {
            var res = new ResultOutput<string>();
            var role = await _roleRepository.FirstOrDefault(q => q.ID == input.Id);
            if (role.IsNull())
            {
                return res.AddError("角色不存在");
            }
            if (roleNamePloy.Contains(input.Name.ToLower()))
            {
                return res.AddError("无法修改成系统角色");
            }
            role.Name = input.Name;
            await _roleRepository.UpdateOne(role);
            return res.ResultInput("修改成功");
        }

        public async Task<ResultOutput> UpdatePowerIdsById(UpdatePowerIdsByIdInput input)
        {
            var res = new ResultOutput();
            var role = await _roleRepository.FirstOrDefault(input.Id);
            if (role.IsNull())
            {
                return res.AddError("角色不存在，请刷新重试");
            }
            var ids = new List<string>();
            if(input.Datas.IsNotNull() && input.Datas.Count > 0)
            {
                await RecursionGetValue(ids, input.Datas);
            }
            role.PowerIds = string.Join(',', ids.ToArray());
            await _roleRepository.UpdateOne(role);
            return res;
        }

        private async Task RecursionGetValue(List<string> ids, IList<TreeData> datas)
        {
            foreach (var item in datas)
            {
                ids.Add(item.Id);
                if (item.Children.Count > 0)
                {
                    await RecursionGetValue(ids, item.Children);
                }
            }
        }
    }
}
